/*****************************************************************************

*This software is developed within IEEE 1857.9 subgroup for the reference test model of Immersive Video Content Coding.
*Contributor: Yueming Wang, wymmail@foxmail.com, Peking University Shenzhen Graduate School

*****************************************************************************/
#include "defines.h"
#ifndef _GLOBAL_H_
#define _GLOBAL_H_

typedef struct coordinate{
	float latitude;//[-pi/2, pi/2]
	float longitude;//[-pi, pi]
}coordinate;

typedef struct ISP_FacePro{
 int id;
 int rotation;
}ISP_FacePro;

typedef struct ISP_FrmStruct{
	int rows;
	int cols;
	ISP_FacePro faces[12][12];
}ISP_FrmStruct;


typedef struct configureInfo{

	//cube map configure Info
	int CubicFaceOrder[NUM_CUBIC_FACE];
	int CubicFaceRotation[NUM_CUBIC_FACE];
	int CubicType;
	int DefaultCubicLayoutFlag;
	int layout_array[6];  // describes left, front, right, rear, top, bottom to be shown in what order
	int layout_rotate[6];
	int layoutWidth;

#if asyerp
    int roi_width;
    int roi_height;
    int visual_width;
    int visual_height;
#endif

#if ISP
	//isp configure Info
	ISP_FrmStruct framePackStruct; // give the index of the face in the i-th row and j-th col 
	int isp_facePos[MAX_FACE][2]; // give the row and col address of the face with index i
#endif

	//ASC and ASCube
	int Viewpoint_center_latitude;
	int Viewpoint_center_longitude;

#if ASC
	int ASC_Z1;	   // Angle of area I on the sphere, degree measure
	int ASC_Z2;	   // Angle of area II on the sphere, degree measure
	int ASC_p1;	   // Radius of area I on the plane
#endif

#if MTK_SS_CUBE
	int x_factor;
#endif
#if MTK_ORIENTATION  
	int rotation_roll;  
	int rotation_yaw;
	int rotation_pitch;
	int orientation_detection;
	int transformation;
#endif  
}configureInfo;

typedef struct sourceInfo{
	// width and height of image
	int width;
	int height;
	// width and height of every face
	int face_width[MAX_FACE];
	int face_height[MAX_FACE];

	int frame_nums;
	int size_y;   // used to malloc buffer
	int face_number;
	char* format;
	unsigned char* buf_y;
	unsigned char* buf_u;
	unsigned char* buf_v;
	char* file_name;
	FILE* file;
	int i_src;   // used to interpolation
	int padding_flag;
	unsigned char padding_val;
	int isChroma;

#if ISP
	unsigned char*** m_pFacesBuf;  //The face of a polyhedron is a triangle, triangles need to be expanded into rectangles to store, So need this buffer
	unsigned char*** m_pFacesOrig;  //The face of a polyhedron is a triangle, triangles need to be expanded into rectangles to store, So need this buffer
#endif
#ifdef MTKVP
    int vp_center_raw;
	int vp_center_pitch;
	int hFOV;
	int vFOV;
#endif
}sourceInfo;
#if ISP
typedef struct TriMesh{
	double vertex[3][3];
	double normVec[3];
	double origin[3];
	double baseVec[2][3];
}TriMesh;
TriMesh meshFaces[MAX_FACE];
#endif


static __inline float clip(float f, float a, float z){
	return (f < a) ? a : (f > z) ? z : f;
}

static __inline int clip_int(int f, int a, int z){
	return (f < a) ? a : (f > z) ? z : f;
}

void init_function_init(sourceInfo *input_Info, sourceInfo *output_Info);//set init_in and init_in_frame
void init_function_map(sourceInfo *input_Info, sourceInfo *output_Info);//set 
void init_function_filter(sourceInfo *input_Info, sourceInfo *output_Info);
void init_function_psnr(sourceInfo *input_Info, sourceInfo *output_Info);
void init_function_cfi(sourceInfo *input_Info, sourceInfo *output_Info);
void init_function_post_tread(sourceInfo *input_Info, sourceInfo *output_Info);
void init_function_pre_tread(sourceInfo *input_Info, sourceInfo *output_Info);

typedef struct{
	void(*init_in)(sourceInfo * source_Info, configureInfo *cfi, int is_input);
	void(*init_out)(sourceInfo * source_Info, configureInfo *cfi, int is_input);
	void(*init_in_frame)(sourceInfo *input, configureInfo *cfi_in, unsigned char *dst[3][MAX_FACE], int is_input);
	void(*init_out_frame)(sourceInfo *output, configureInfo *cfi_out, unsigned char *dst[3][MAX_FACE], int is_input);
	
	void(*output_map_to_sphere)(sourceInfo *output, configureInfo *cfi_out, int dst_k, float dst_i, float dst_j, coordinate *sphere);
	void(*sphere_map_to_input)(sourceInfo *input, configureInfo *cfi_in, int *src_k, float *src_i, float *src_j, coordinate *sphere);
	void(*sphere_map_to_output)(sourceInfo *input, configureInfo *cfi_in, int *src_k, float *src_i, float *src_j, coordinate *sphere);
	
	void(*init_lanczos_filter)();
	float(*filter)(unsigned char * src, float i, float j, int input_width, int input_height, int i_src);
	
	unsigned char*(*getDst)(int dst_i, int dst_j, int dst_k, sourceInfo *output, configureInfo *cfi_out, unsigned char *dst[]);
	void (*map_one_frame)(sourceInfo *input, sourceInfo *output, configureInfo *cfi_in, configureInfo *cfi_out);

	void(*pre_tread_in)(sourceInfo *input, configureInfo *cfi_in, unsigned char *src[3][MAX_FACE]);
	void(*pre_tread_out)(sourceInfo *input, configureInfo *cfi_in, unsigned char *src[3][MAX_FACE]);
	void(*post_tread_out)(sourceInfo *output, configureInfo *cfi_out, unsigned char *dst[3][MAX_FACE]);
	
	void (*calculation_psnr)(sourceInfo *input, sourceInfo *output, configureInfo *cfi_in, configureInfo *cfi_out, float * psnr);
	void (*calculation_spsnr)(sourceInfo *input, sourceInfo *output, configureInfo *cfi_in, configureInfo *cfi_out, coordinate * sphere_point, int sphere_num, float * spsnr);
	
	char *(*GetConfigFileContent_in)(char *Filename);
	void (*ParseContent_in)(char *buf, int bufsize, configureInfo *cfi);
	char *(*GetConfigFileContent_out)(char *Filename);
	void(*ParseContent_out)(char *buf, int bufsize, configureInfo *cfi);
}function;

function handle_function;

#if MTK_ORIENTATION == 1
void sphere2cart(coordinate *sph, float *c);
void cart2sphere(float *c, coordinate *sph);
void content_rotation(float *sphere, int roll, int yaw, int pitch);
void content_inv_rotation(float *sphere, int roll, int yaw, int pitch);
int content_orientation(sourceInfo *input_Info, configureInfo *cfi_in);
int save_yuv_file(unsigned char *p_data, int width, int height, char * filename);
int normmalize_data(unsigned int *p_data, unsigned char * p_norm_data, size_t count, unsigned int *p_max_data, unsigned int * p_min_data);
#if PKU_IMPROVE_ROTATION == 1
void sphere_rotation(int phi_in, int theta_in, int *phi_out, int *theta_out, int pole_phi, int pole_theta);
#endif

#endif

#if PKU_IMPROVE_ROTATION == 1

#endif

#endif
